home *** CD-ROM | disk | FTP | other *** search
/ BMUG Revelations / BMUG Revelations.toast / Telecom / Terminal Programs / Terminal 2.0 / Srcs / File.c < prev    next >
Text File  |  1990-11-20  |  19KB  |  764 lines

  1. /*
  2.     Terminal 2.0
  3.     "File.c"
  4. */
  5.  
  6. #ifdef THINK_C
  7. #include "MacHeaders"
  8. #endif
  9. #ifdef applec
  10. #pragma load ":(Objects):MacHeadersMPW"
  11. #pragma segment Main2
  12. #endif
  13.  
  14. #include "File.h"
  15. #include "Text.h"
  16. #include "Main.h"
  17. #include "Strings.h"
  18. #include "Utilities.h"
  19. #include "MySF.h"
  20. #include "Document.h"
  21. #include "Serial.h"
  22. #include "CancelDialog.h"
  23. #include "XModem.h"
  24. #include "ZModem.h"
  25. #include "MacBinary.h"
  26. #include "FormatStr.h"
  27. #include "Interp.h"
  28.  
  29. /* ----- Static data --------------------------------------------------- */
  30.  
  31. static jmp_buf env;
  32. static short ScriptRef;            /* Script file reference */
  33. static short ScriptUnget;        /* Script file unget buffer */
  34. static Byte *ScriptBuffer;        /* Script file buffer */
  35. static long ScriptEob;            /* Size of script file buffer */
  36. static long ScriptMark;            /* Next position in script file buffer */
  37. extern INTRINSIC Intrinsics[];    /* Script intrinsic functions */
  38.  
  39. /* ----- Text capture -------------------------------------------------- */
  40.  
  41. void TextCapture(short options)
  42. {
  43.     register DocumentPeek window = TerminalWindow;
  44.     SFReply sfr;
  45.     short r;
  46.  
  47.     /* If capture is on the off */
  48.  
  49.     if (window->file) {
  50.         if (window->length) {
  51.             if (FSWrite(window->file, &window->length, window->record))
  52.                 SysBeep(1);
  53.         }
  54.         FSClose(window->file);
  55.         FlushVol(0, window->volume);
  56.         window->file = window->volume = 0;
  57.         window->length = 0;
  58.         SetItemStyle(GetMenu(FILE), CAPTURE, 0);
  59.         return;
  60.     }
  61.  
  62.     /* If capture is off then on */
  63.  
  64.     if (options & (optionKey | cmdKey | shiftKey | controlKey)) {
  65.         /* Append to existing file */
  66.         MySFGetFile(MyString(STR_G, G_APPEND), 0, 1, &TEXT, &sfr, 0);
  67.         if (!sfr.good)    /* Cancel */
  68.             return;
  69.         if (OpenFile(sfr.vRefNum, 0, (Byte *)sfr.fName, &r)) {
  70.             SysBeep(1);
  71.             return;
  72.         }
  73.         if (SetFPos(r, fsFromLEOF, 0)) {
  74.             FSClose(r);
  75.             SysBeep(1);
  76.             return;
  77.         }
  78.     } else {
  79.         /* Open new file */
  80.         MySFPutFile(MyString(STR_G, G_SAVE), MyString(STR_G, G_CTFILE),
  81.             MyString(STR_G, G_CAPTURE), &sfr);
  82.         if (!sfr.good)    /* Cancel */
  83.             return;
  84.         DeleteFile(sfr.vRefNum, 0, (Byte *)sfr.fName);
  85.         if (CreateFile(sfr.vRefNum, 0, (Byte *)sfr.fName,
  86.                 Settings.textCreator, TEXT) ||
  87.                 OpenFile(sfr.vRefNum, 0, (Byte *)sfr.fName, &r)) {
  88.             SysBeep(1);
  89.             return;
  90.         }
  91.     }
  92.     window->file = r;
  93.     window->volume = sfr.vRefNum;
  94.     SetItemStyle(GetMenu(FILE), CAPTURE, ACTIVE);
  95. }
  96.  
  97. /* ----- Save one byte in capture file --------------------------------- */
  98.  
  99. void ByteCapture(register Byte b)
  100. {
  101.     register DocumentPeek window = TerminalWindow;
  102.     register short err;
  103.  
  104.     if (window->file) {
  105.         window->record[(window->length)++] = b;
  106.         if (window->length == RECORD) {
  107.             err = FSWrite(window->file, &window->length, window->record);
  108.             window->length = 0;
  109.             if (err) {
  110.                 TextCapture(0);    /* Close file */
  111.                 Error(err, EmptyStr);
  112.             }
  113.         }
  114.     }
  115. }
  116.  
  117. /* ----- Save text of window ------------------------------------------- */
  118.  
  119. void SaveBuffer(short options)
  120. {
  121.     register DocumentPeek window = TerminalWindow;
  122.     register Byte *p;
  123.     register short err;
  124.     SFReply sfr;
  125.     short r;
  126.     long count;
  127.  
  128.     if (window->buf.newChar == window->buf.firstChar)    /* Empty */
  129.         return;
  130.     if (options & (optionKey | cmdKey | shiftKey | controlKey)) {
  131.         /* Append to existing file */
  132.         MySFGetFile(MyString(STR_G, G_APPEND), 0, 1, &TEXT, &sfr, 0);
  133.         RedrawDocument();
  134.         if (!sfr.good)    /* Cancel */
  135.             return;
  136.         if (OpenFile(sfr.vRefNum, 0, (Byte *)sfr.fName, &r))
  137.             goto done2;
  138.         if (SetFPos(r, fsFromLEOF, 0))
  139.             goto done1;
  140.     } else {
  141.         /* Create new file */
  142.         MySFPutFile(MyString(STR_G, G_SAVE), MyString(STR_G, G_SCBUFFER),
  143.             MyString(STR_G, G_BUFFER), &sfr);
  144.         RedrawDocument();
  145.         if (!sfr.good)    /* Cancel */
  146.             return;
  147.         DeleteFile(sfr.vRefNum, 0, (Byte *)sfr.fName);
  148.         if ((err = CreateFile(sfr.vRefNum, 0, (Byte *)sfr.fName,
  149.                 Settings.textCreator, TEXT)) ||
  150.                 (err = OpenFile(sfr.vRefNum, 0, (Byte *)sfr.fName, &r)))
  151.             goto done2;
  152.     }
  153.     p = window->buf.text;
  154.     if (window->buf.newChar > window->buf.firstChar) {    /* One part */
  155.         count = window->buf.newChar - window->buf.firstChar;
  156.         err = FSWrite(r, &count, p + window->buf.firstChar);
  157.     } else {                                            /* Two parts */
  158.         count = window->buf.size - window->buf.firstChar;
  159.         if (err = FSWrite(r, &count, p + window->buf.firstChar))
  160.             goto done1;
  161.         if (count = window->buf.newChar)
  162.             err = FSWrite(r, &count, p);
  163.     }
  164. done1:
  165.     FSClose(r);
  166.     FlushVol(0, sfr.vRefNum);
  167. done2:
  168.     if (err)
  169.         Error(err, EmptyStr);
  170. }
  171.  
  172. /* ----- Send text file ------------------------------------------------ */
  173.  
  174. short pascal SendTextFile(
  175.     short ref,                    /* File reference number */
  176.     Byte *name)                    /* File name */
  177. {
  178.     register short err;            /* Error code */
  179.     register long count;        /* File read count */
  180.     register Byte buffer[256];    /* Transmit buffer */
  181.     HParamBlockRec p;            /* Used for PBRead() */
  182.     long mark = 0;                /* Current file position */
  183.     long time;                    /* How long it takes */
  184.  
  185.     if (SendFileRef || Sending || Transfer)
  186.         return fBsyErr;
  187.     SendFileRef = ref;
  188.     Sending = TRUE;
  189.     Control_X = FALSE;
  190.     SetItemStyle(GetMenu(FILE), SEND, ACTIVE);
  191.     MakeMessage(TerminalWindow,
  192.         FormatStr(buffer, MyString(STR_P, P_STEXT), name));
  193.     /* SerialHandshake(Settings.handshake); */
  194.     p.ioParam.ioCompletion = 0;
  195.     p.ioParam.ioRefNum = ref;
  196.     p.ioParam.ioBuffer = (Ptr)buffer;
  197.     p.ioParam.ioReqCount = (Settings.chardelay) ? 1 : sizeof(buffer) - 1;
  198.     p.ioParam.ioPosMode =
  199.         (Settings.linedelay || Settings.prompt[0] || Settings.autoLF) ?
  200.         (0x0D80 | fsAtMark) : fsAtMark;    /* CR as newline (if necessary) */
  201.     time = Time;
  202.     do {
  203.         err = PBRead((ParmBlkPtr)&p, FALSE);
  204.         count = p.ioParam.ioActCount;
  205.         if ((err == noErr || err == eofErr) && count) {
  206.             while (Busy)    /* Other send in progress */
  207.                 ;
  208.             if (buffer[count-1] == '\015') {
  209.                 if (Settings.autoLF)
  210.                     buffer[count++] = '\012';
  211.                 SerialSend(buffer, count, &Busy);
  212.                 if (Settings.localEcho)
  213.                     NewCharacters(buffer, count, FALSE);
  214.                 if (Settings.linedelay || Settings.prompt[0])
  215.                     Loop(Settings.linedelay,Settings.prompt,1);
  216.                 else
  217.                     CheckEvents();
  218.             } else {
  219.                 SerialSend(buffer, count, &Busy);
  220.                 if (Settings.localEcho)
  221.                     NewCharacters(buffer, count, FALSE);
  222.                 if (Settings.chardelay)
  223.                     Loop(Settings.chardelay, 0, 0);
  224.                 else
  225.                     CheckEvents();
  226.             }
  227.             mark += count;
  228.         }
  229.     } while (err == noErr && Sending);
  230.  
  231.     if (err == eofErr)
  232.         err = noErr;
  233.     if (!Sending)
  234.         err = Control_X ? ABORT : CANCEL;
  235.     Statistics(mark, time = Time - time, err);
  236.     SetItemStyle(GetMenu(FILE), SEND, 0);
  237.     FSClose(ref);
  238.     SendFileRef = 0;
  239.     Sending = FALSE;
  240.     Control_X = FALSE;
  241.     /* SerialHandshake(0); */
  242.     return err;
  243. }
  244.  
  245. /* ----- Get text file name and send text file ------------------------- */
  246.  
  247. void SendText(void)
  248. {
  249.     register short err;
  250.     SFReply sfr;
  251.     short r;
  252.  
  253.     if (Transfer) {
  254.         SysBeep(1);
  255.         return;
  256.     }
  257.     if (!Sending) {
  258.         MySFGetFile(MyString(STR_G, G_SEND), 0, 1, &TEXT, &sfr, 0);
  259.         RedrawDocument();
  260.         if (!sfr.good)
  261.             return;
  262.         if (err = OpenFile(sfr.vRefNum, 0, (Byte *)sfr.fName, &r)) {
  263.             Error(err, EmptyStr);
  264.             return;
  265.         }
  266.         err = SendTextFile(r, (Byte *)sfr.fName);
  267.     } else {
  268.         SerialAbort();
  269.         Sending = FALSE;
  270.     }
  271. }
  272.  
  273. /* ----- Send text ----------------------------------------------------- */
  274.  
  275. static short TypeText(
  276.     register Byte *s,            /* -> text to send */
  277.     register long n)            /* Number of characters in text */
  278. {
  279.     register long count;        /* File read count */
  280.     register Byte buffer[256];    /* Transmit buffer */
  281.     short req;                    /* Max byte count */
  282.     Boolean cr;                    /* Look for CR */
  283.     short err;                    /* Error code */
  284.     long mark = 0;                /* Current file position */
  285.     long time;                    /* How long it takes */
  286.  
  287.     Sending = TRUE;
  288.     Control_X = FALSE;
  289.     SetItemStyle(GetMenu(EDIT), PASTE, ACTIVE);
  290.     MakeMessage(TerminalWindow,
  291.         FormatStr(buffer, MyString(STR_P, P_SSCRAP)));
  292.     /* SerialHandshake(Settings.handshake); */
  293.     if (Settings.chardelay) {
  294.         req = 1;
  295.         cr = FALSE;
  296.     } else {
  297.         req = sizeof(buffer) - 1;
  298.         cr = Settings.linedelay || Settings.prompt[0] || Settings.autoLF;
  299.     }
  300.     time = Time;
  301.     do {
  302.         count = (req < n) ? req : n;
  303.         if (cr)
  304.             count = (Byte *)memchr(s, 13, count) - s + 1;
  305.         n -= count;
  306.         memcpy(buffer, s, count);
  307.         s += count;
  308.         if (count) {
  309.             while (Busy)    /* Other send in progress */
  310.                 ;
  311.             if (buffer[count-1] == '\015') {
  312.                 if (Settings.autoLF)
  313.                     buffer[count++] = '\012';
  314.                 SerialSend(buffer, count, &Busy);
  315.                 if (Settings.localEcho)
  316.                     NewCharacters(buffer, count, FALSE);
  317.                 if (Settings.linedelay || Settings.prompt[0])
  318.                     Loop(Settings.linedelay, Settings.prompt, 1);
  319.                 else
  320.                     CheckEvents();
  321.             } else {
  322.                 SerialSend(buffer, count, &Busy);
  323.                 if (Settings.localEcho)
  324.                     NewCharacters(buffer, count, FALSE);
  325.                 if (Settings.chardelay)
  326.                     Loop(Settings.chardelay, 0, 0);
  327.                 else
  328.                     CheckEvents();
  329.             }
  330.             mark += count;
  331.         }
  332.     } while (n && Sending);
  333.     if (!n)
  334.         err = noErr;
  335.     if (!Sending)
  336.         err = Control_X ? ABORT : CANCEL;
  337.     /* Statistics(mark, time = Time - time, err); */
  338.     SetItemStyle(GetMenu(EDIT), PASTE, 0);
  339.     Sending = FALSE;
  340.     Control_X = FALSE;
  341.     /* SerialHandshake(0); */
  342.     return err;
  343. }
  344.  
  345. /* ----- Send TEXT from scrap ------------------------------------------ */
  346.  
  347. void SendScrap(void)
  348. {
  349.     register Handle h;
  350.     register long err;
  351.     long offset;
  352.  
  353.     if (Transfer) {
  354.         SysBeep(1);
  355.         return;
  356.     }
  357.     if (Sending) {
  358.         SerialAbort();
  359.         Sending = FALSE;
  360.     } else {
  361.         if (h = NewHandle(0)) {
  362.             if ((err = GetScrap(h,TEXT,&offset)) > 0) {
  363.                 HLock(h);
  364.                 TypeText((Byte *)*h, err);
  365.                 err = noErr;
  366.             }
  367.             DisposHandle(h);
  368.         } else
  369.             err = memFullErr;
  370.         if (err)
  371.             Error(err, EmptyStr);
  372.     }
  373. }
  374.  
  375. /* ----- Receive file -------------------------------------------------- */
  376.  
  377. void FileReceive(void)
  378. {
  379.     register short err;
  380.     SFReply sfr;
  381.  
  382.     if (Sending) {
  383.         SysBeep(1);
  384.         return;
  385.     }
  386.     if (!Transfer) {
  387.         if (Settings.ZModem) {
  388.             err = ZReceive();
  389.             UnloadSeg(ZReceive);
  390.         } else
  391.             if (Settings.batch) {
  392.                 err = XReceive(EmptyStr, 0, 0);
  393.                 UnloadSeg(XReceive);
  394.             } else {
  395.                 MySFPutFile(MyString(STR_G, G_RECEIVE),
  396.                     MyString(STR_G, G_SFRECEIVE),
  397.                     MyString(STR_G, G_DOWNLOAD), &sfr);
  398.                 RedrawDocument();
  399.                 if (sfr.good) {
  400.                     DeleteFile(sfr.vRefNum, 0, (Byte *)sfr.fName);
  401.                     err = XReceive((Byte *)sfr.fName, sfr.vRefNum, 0);
  402.                     UnloadSeg(XReceive);
  403.                 }
  404.             }
  405.     } else
  406.         Transfer = 0;    /* Cancel transfer */
  407. }
  408.  
  409. /* ----- Transmit file ------------------------------------------------- */
  410.  
  411. void FileTransmit(void)
  412. {
  413.     register short err;
  414.     SFReply sfr;
  415.  
  416.     if (Sending) {
  417.         SysBeep(1);
  418.         return;
  419.     }
  420.     if (!Transfer) {
  421.         MySFGetFile (MyString(STR_G, G_TRANSMIT), 0, -1, 0, &sfr, 0);
  422.         RedrawDocument();
  423.         if (sfr.good) {
  424.             if (Settings.ZModem) {
  425.                 err = ZTransmit((Byte *)sfr.fName, sfr.vRefNum, 0);
  426.                 UnloadSeg(ZTransmit);
  427.             } else {
  428.                 err = XTransmit((Byte *)sfr.fName, sfr.vRefNum, 0);
  429.                 UnloadSeg(XTransmit);
  430.             }
  431.         }
  432.     } else
  433.         Transfer = 0;    /* Cancel transfer */
  434. }
  435.  
  436. /* ----- Make MacBinary file ------------------------------------------- */
  437.  
  438. short Convert(
  439.     short volume1, long dir1, Byte *name1,
  440.     short volume2, long dir2, Byte *name2)
  441. {
  442.     register short err, err2;
  443.     register Handle buf;
  444.     register unsigned long size;
  445.     Boolean mf;
  446.     short ref2;
  447.     long count;
  448.  
  449.     if ((err = BinOpenRead(volume1, dir1, name1)) ||
  450.             (err = CreateFile(volume2, dir2, name2, Application.signature,
  451.                 Application.btype)) ||
  452.             (err = OpenFile(volume2, dir2, name2, &ref2)))
  453.         return err;
  454.     if ((size = MaxBuffer(&mf)) < 128 || !(buf = NewBuffer(size, mf)))
  455.         return memFullErr;
  456.     err2 = 0;
  457.     do {
  458.         count = size;
  459.         if (!(err = BinRead(&count, (Byte *)*buf)) || err == eofErr)
  460.             err2 = FSWrite(ref2, &count, *buf);
  461.     } while(!err && !err2);
  462.     DisposeBuffer(buf, mf);
  463.     BinCloseRead();
  464.     FSClose(ref2);
  465.     FlushVol(0, volume2);
  466.     if (err == eofErr)
  467.         err = 0;
  468.     return err2 ? err2 : err;
  469. }
  470.  
  471. void Make(void)
  472. {
  473.     SFReply r1, r2;
  474.     register Byte *suffix;
  475.     register Byte name[256];
  476.     register long n;
  477.     register short err;
  478.  
  479.     suffix = MyString(STR_G, G_BIN);
  480.     MySFGetFile(MyString(STR_G, G_MAKE), 0, -1, 0, &r1, 0);
  481.     if (!r1.good)
  482.         return;
  483.     RedrawDocument();
  484.     memcpy(name, r1.fName, n = (r1.fName[0] + 1));
  485.     memcpy(name + n, suffix + 1, suffix[0]);
  486.     name[0] += suffix[0];
  487.     MySFPutFile(MyString(STR_G, G_SAVE), MyString(STR_G, G_MAKENAME),
  488.         name, &r2);
  489.     if (!r2.good)
  490.         return;
  491.     RedrawDocument();
  492.     DeleteFile(r2.vRefNum, 0, (Byte *)r2.fName);
  493.     if (err = Convert(r1.vRefNum, 0, (Byte *)r1.fName,
  494.             r2.vRefNum, 0, (Byte *)r2.fName))
  495.         Error(err, EmptyStr);
  496. }
  497.  
  498. /* ----- Extract from MacBinary file ----------------------------------- */
  499.  
  500. short CopyFile(register short ref1)
  501. {
  502.     register short err, err2;
  503.     long count;
  504.     register Handle buf;
  505.     register unsigned long size;
  506.     Boolean mf;
  507.  
  508.     if ((size = MaxBuffer(&mf)) < 128 || !(buf = NewBuffer(size, mf)))
  509.         return memFullErr;
  510.     err2 = 0;
  511.     do {
  512.         count = size;
  513.         if (!(err = FSRead(ref1, &count, *buf)) || err == eofErr)
  514.             err2 = BinWrite(&count, (Byte *)*buf);
  515.     } while(!err && !err2);
  516.     DisposeBuffer(buf, mf);
  517.     if (err == eofErr)
  518.         err = 0;
  519.     return err ? err : err2;
  520. }
  521.  
  522. void Extract(void)
  523. {
  524.     SFReply r1, r2;
  525.     short ref1;
  526.     Byte name[64];
  527.     Byte header[BinHeaderLength];
  528.     long count, data, resource;
  529.     register short err, err2;
  530.  
  531.     MySFGetFile(MyString(STR_G, G_EXTRACT), 0, -1, 0, &r1, 0);
  532.     if (!r1.good)
  533.         return;
  534.     RedrawDocument();
  535.  
  536.     if (err = OpenFile(r1.vRefNum, 0, (Byte *)r1.fName, &ref1))
  537.         goto sorry1;
  538.  
  539.     count = sizeof(header);
  540.     if ((err = FSRead(ref1, &count, header)) || count != sizeof(header))
  541.         goto sorry;
  542.  
  543.     if (!BinCheckHeader(header, name, &data, &resource)) {
  544.         err = 1;
  545.         goto sorry;
  546.     }
  547.  
  548.     MySFPutFile(MyString(STR_G, G_SAVE), MyString(STR_G, G_SFEXTRACT),
  549.         name, &r2);
  550.     if (!r2.good)
  551.         goto sorry;
  552.     RedrawDocument();
  553.  
  554.     DeleteFile(r2.vRefNum, 0, (Byte *)r2.fName);
  555.     if (err = CreateFile(r2.vRefNum, 0, (Byte *)r2.fName, '????', '????'))
  556.         goto sorry;
  557.  
  558.     if (err = BinOpenWrite(r2.vRefNum, 0, (Byte *)r2.fName, header))
  559.         goto sorry;
  560.  
  561.     err = CopyFile(ref1);
  562.     err2 = BinCloseWrite();
  563.     if (!err)
  564.         err = err2;
  565.  
  566. sorry:
  567.     FSClose(ref1);
  568. sorry1:
  569.     if (err)
  570.         Error(err, EmptyStr);
  571. }
  572.  
  573. /* ----- Get text file name and execute script ------------------------- */
  574.  
  575. #define SCRIPTSIZE    512                /* Script file buffer size */
  576. #define SCRIPTMAX    Config.script    /* Memory size for script */
  577.  
  578. static Boolean Script(void)
  579. {
  580.     register short err;
  581.     register Boolean quit = FALSE;
  582.     Options save;
  583.  
  584.     ScriptBuffer = 0;
  585.     if (!(ScriptBuffer = (Byte *)NewPtr(SCRIPTSIZE + SCRIPTMAX))) {
  586.         err = MemError();
  587.         goto done;
  588.     }
  589.     ScriptUnget = -1;            /* No unget character yet */
  590.     ScriptMark = ScriptEob = SCRIPTSIZE;    /* Buffer is still empty */
  591.  
  592.     save = Settings;            /* Save settings */
  593.     if (setjmp(env) == 0) {
  594.         SI_Load(Intrinsics, ScriptBuffer + SCRIPTSIZE, SCRIPTMAX);
  595.         FSClose(ScriptRef);        /* Script file no longer needed */
  596.         ScriptRef = 0;
  597.         err = SI_Interpret();    /* Call main() in script */
  598.     } else {                    /* Come here after error */
  599.         err = 1;                /* Always restore settings if error */
  600.         SysBeep(1);
  601.     }
  602.     /*
  603.         The script main() can return the following values:
  604.             0    : Don't restore saved settings, continue application
  605.             1    : Restore saved settings, continue application
  606.             256    : Don't restore saved settings, quit application
  607.             257    : Restore saved settings, quit application
  608.     */
  609.     if (err == 1 || err == 257) {    /* Restore settings */
  610.         if (save.portSetup != Settings.portSetup ||
  611.                 !EqualString(save.portName, Settings.portName, FALSE, TRUE) ||
  612.                 save.handshake != Settings.handshake) {
  613.             SerialClose();
  614.             SerialOpen(save.portName, save.portSetup, save.handshake);
  615.         }
  616.         Settings = save;
  617.     }
  618.     if (err == 256 || err == 257)    /* Quit application */
  619.         quit = TRUE;
  620.     err = noErr;
  621.  
  622. done:
  623.     if (ScriptBuffer)
  624.         DisposPtr(ScriptBuffer);
  625.     if (ScriptRef)
  626.         FSClose(ScriptRef);
  627.     if (err) {
  628.         SysBeep(1);
  629.         Error(err, EmptyStr);
  630.     }
  631.     return quit;
  632. }
  633.  
  634. static Boolean ScriptFlag = 0;
  635.  
  636. Boolean RunScript(
  637.     short volume,
  638.     long directory,
  639.     Byte *name,
  640.     short item)
  641. {
  642.     register short err;
  643.     register Byte *n;
  644.     register Boolean quit = FALSE;
  645.     SFReply sfr;
  646.  
  647.     if (Transfer) {
  648.         SysBeep(1);
  649.         return quit;
  650.     }
  651.     if (ScriptFlag) {        /* Cancel script */
  652.         Abort = TRUE;
  653.         Sending = FALSE;
  654.         SerialAbort();
  655.     } else {                /* Execute script file */
  656.         if (name)
  657.             err = OpenFile(volume, directory, n = name, &ScriptRef);
  658.         else {
  659.             MySFGetFile(MyString(STR_G,G_SCRIPT),
  660.                 MyString(STR_G,G_SUFFIX),
  661.                 1, &TEXT, &sfr, 0);
  662.             RedrawDocument();
  663.             if (!sfr.good)
  664.                 return quit;
  665.             err = OpenFile(sfr.vRefNum, 0, n = (Byte *)sfr.fName,
  666.                 &ScriptRef);
  667.         }
  668.         if (err) {
  669.             Error(err, EmptyStr);
  670.             return quit;
  671.         }
  672.         Abort = FALSE;
  673.         ScriptFlag = item;
  674.         SetWTitle((WindowPtr)TerminalWindow, n);
  675.         SetItemStyle(GetMenu(SCRIPT), item, ACTIVE);
  676.         quit = Script();
  677.         SetItemStyle(GetMenu(SCRIPT), item, 0);
  678.         Abort = TRUE;
  679.         ScriptFlag = 0;
  680.     }
  681.     return quit;
  682. }
  683.  
  684. Boolean DoMenuScript(register short item)
  685. {
  686.     register Byte name[256];
  687.  
  688.     GetItem(GetMenu(SCRIPT), item, name);
  689.     Append(name, MyString(STR_G, G_SUFFIX));
  690.     return RunScript(Settings.scriptVolume, Settings.scriptDirectory, name, item);
  691. }
  692.  
  693. /* ----- Functions called by interpreter ------------------------------- */
  694.  
  695. void SI_Error(
  696.     register short erno,
  697.     register Byte *s,
  698.     register short line)
  699. {
  700.     register Byte message[256];
  701.  
  702.     erno += 2;
  703.     if (*s) {
  704.         CtoPstr((char *)s);
  705.         FormatStr(message,MyString(STR_S,1),s,MyString(STR_S,erno),line);
  706.         PtoCstr((char *)s);
  707.     } else
  708.         FormatStr(message,MyString(STR_S,2),MyString(STR_S,erno),line);
  709.     MakeMessage(TerminalWindow, message);
  710.     longjmp(env, 0);    /* Return to Script(), ignore link chain */
  711. }
  712.  
  713. short SI_GetSource(void)
  714. {
  715.     register Byte c;
  716.  
  717.     if (ScriptUnget >= 0) {            /* The was a previous unget */
  718.         c = ScriptUnget;            /* So use the unget buffer */
  719.         ScriptUnget = -1;            /* Unget buffer is empty now */
  720.         return c;
  721.     }
  722.     if (ScriptMark < ScriptEob)        /* Can still use buffer */
  723.         return ScriptBuffer[ScriptMark++];
  724.     if (ScriptEob < SCRIPTSIZE)        /* Was last (partial) buffer */
  725.         return -1;                    /* EOF */
  726.     ScriptEob = SCRIPTSIZE;            /* Read next buffer from file */
  727.     FSRead(ScriptRef, &ScriptEob, ScriptBuffer);
  728.     if (ScriptEob > 0) {            /* Ok, at least one character */
  729.         ScriptMark = 0;
  730.         return SI_GetSource();
  731.     }
  732.     return -1;                        /* Error or end of file */
  733. }
  734.  
  735. void SI_UngetSource(register short c)
  736. {
  737.     ScriptUnget = c;                /* That's easy */
  738. }
  739.  
  740. /* ----- Kiss script file ---------------------------------------------- */
  741.  
  742. void Kiss(short options)
  743. {
  744.     SFReply r;
  745.     ParamBlockRec p;
  746.     register OSType creator;
  747.  
  748.     creator = (options & (optionKey | cmdKey | shiftKey | controlKey)) ?
  749.         Settings.textCreator : Application.signature;
  750.     do {
  751.         MySFGetFile(MyString(STR_G,G_KISS), MyString(STR_G,G_SUFFIX),
  752.             1, &TEXT, &r, creator);
  753.         if (r.good) {
  754.             memset(&p, 0, sizeof(p));
  755.             p.fileParam.ioNamePtr = r.fName;
  756.             p.fileParam.ioVRefNum = r.vRefNum;
  757.             if (!PBGetFInfo(&p, FALSE)) {
  758.                 p.fileParam.ioFlFndrInfo.fdCreator = creator;
  759.                 PBSetFInfo(&p, FALSE);
  760.             }
  761.         }
  762.     } while (FALSE /* r.good */);
  763. }
  764.